package org.jdsm.flow.core.utils.impl.objectify;

import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.cmd.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * User: mikom
 * Date: 3/11/13
 * Time: 3:41 PM
 */
public class PersistenceUtils {
    private static final Logger log = LoggerFactory.getLogger(PersistenceUtils.class);

    public static <X> List<X> emptyList() {
        return new ArrayList<X>();
    }

    public static <X> int count(Objectify ofy, Class<X> clazz) {
        if (ofy == null) {
            log.error("Entity manager can't be null");
            return 0;
        }
        if (clazz == null) {
            log.error("Class can't be null");
            return 0;
        }
        log.debug("count entity by class: {}", clazz.getName());
        int result = ofy.load().type(clazz).count();
        log.debug("entities equally: {}", result);
        return result;
    }

    /**
     * method load entities by name(only for IRole, IGroup...)
     *
     * @param ofy   entity manager
     * @param clazz class type
     * @param names field names
     * @param <X>   result type of class type
     * @return result list
     */
    public static <X> List<X> loadEntitiesByName(Objectify ofy, Class<X> clazz, Collection<String> names) {
        if (ofy == null) {
            log.error("Entity manager can't be null");
            return null;
        }
        if (clazz == null) {
            log.error("Class can't be null");
            return null;
        }

        log.debug("load entities:{} by names:{}", clazz.getName(), names);
        List<X> resultList = ofy.load().type(clazz).filter("name", names).list();
        log.debug("result: {}", resultList);
        return resultList;
    }

    /**
     * method load entities by name(only for IRole, IGroup...)
     * @param ofy  entity manager
     * @param clazz class type
     * @param ids field names
     * @param <X> result type of class type
     * @return result list
     */
    public static <X> List<X> loadEntitiesByIds(Objectify ofy, Class<X> clazz, Collection<Long> ids) {
        if (ofy == null) {
            log.error("Entity manager can't be null");
            return null;
        }
        if (clazz == null) {
            log.error("Class can't be null");
            return null;
        }

        log.debug("load entities:{} by ids:{}", clazz.getName(), ids);
        List<X> resultList = new ArrayList<X>(ofy.load().type(clazz).ids(ids).values());
        log.debug("result: {}", resultList);
        return resultList;
    }

    public static <X> List<X> loadedByCriteria(Objectify ofy, Class<X> clazz, int maxResult,
                                               int startResult, boolean isSort, String field) {
        if (ofy == null) {
            log.error("Entity manager can't be null");
            return null;
        }
        if (clazz == null) {
            log.error("Class can't be null");
            return null;
        }
        log.debug("load data by criteria# maxResult:{}, start:{}, isSort:{}, sorted field:{}",
                new Object[]{maxResult, startResult, isSort, field});


        Query<X> query = ofy.load().type(clazz).offset(startResult).limit(maxResult);
        if (field != null && !"".equals(field)) {
            String prefix = "";
            if (!isSort) prefix = "-";
            query.order(prefix + field);
        }

        List<X> results = query.list();
        if (log.isDebugEnabled()) {
            for (X obj : results) {
                log.debug("was loaded data obj: {}", obj);
            }
        }
        return results;
    }
}
